package com.uchonor.api.core.service;

import com.uchonor.api.core.entity.InterfaceConfig;
import com.uchonor.api.core.entity.InterfaceParameterConfig;
import com.uchonor.api.core.template.AbstractTemplateEngine;
import com.uchonor.olight.agent.annotation.Inject;
import com.uchonor.olight.agent.utils.AssertUtils;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.ssssssss.magicapi.core.model.*;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

public abstract class LowCodeApi {
    protected ResourceService resourceService;
    protected AbstractTemplateEngine abstractTemplateEngine;

    public abstract boolean isSupper(String interfaceType);

    public LowCodeApi(ResourceService resourceService, AbstractTemplateEngine abstractTemplateEngine) {
        this.resourceService = resourceService;
        this.abstractTemplateEngine = abstractTemplateEngine;
    }

    /**
     * 生成执行代码信息
     */
    public abstract void generateScriptCode(ApiInfo magicEntity,Map<String,Object> dataMap) throws TemplateException, IOException;

    /**
     * 生成接口相关的信息
     *
     * @param magicEntity
     * @param interfaceConfig
     */
    public void generateInterfaceInfo(ApiInfo magicEntity, InterfaceConfig interfaceConfig) {
        magicEntity.setId(interfaceConfig.getInterfaceId());
        magicEntity.setCreateBy(interfaceConfig.getCreateUser());
        magicEntity.setCreateTime(interfaceConfig.getCreateTime() != null ? interfaceConfig.getCreateTime().getTime() : null);
        magicEntity.setGroupId(interfaceConfig.getGroupId());
        magicEntity.setName(interfaceConfig.getInterfaceName());
        magicEntity.setUpdateBy(interfaceConfig.getUpdateUser());
        magicEntity.setUpdateTime(interfaceConfig.getUpdateTime() != null ? interfaceConfig.getUpdateTime().getTime() : null);
        magicEntity.setDescription(interfaceConfig.getInterfaceDesc());
        magicEntity.setPath(interfaceConfig.getInterfaceUrl());
        magicEntity.setRequestBody(interfaceConfig.getInterfaceRequestBody());
        magicEntity.setMethod(interfaceConfig.getInterfaceMethod());
    }

    private void setBaseDefinition(BaseDefinition parameter, InterfaceParameterConfig item) {
        parameter.setDescription(item.getParameterDesc());
        parameter.setName(item.getParameterKey());
        parameter.setDefaultValue(item.getParameterDefaultValue());
        parameter.setRequired("1".equals(item.getParameterRequired()));
        parameter.setDataType(StringUtils.isNotBlank(item.getParameterType())?DataType.valueOf(item.getParameterType()):null);
        parameter.setValidateType(item.getParameterValidationType());
        parameter.setError(item.getParameterValidationTips());
        parameter.setExpression(item.getParameterValidationContent());
    }

    /**
     * 设置请求参数
     *
     * @param magicEntity
     * @param requestParamList
     */
    public void generateRequestParam(ApiInfo magicEntity, List<InterfaceParameterConfig> requestParamList) {
        if (requestParamList != null && requestParamList.size() > 0) {
            List<Parameter> parameterList = new ArrayList<>();
            requestParamList.forEach(item -> {
                Parameter parameter = new Parameter();
                setBaseDefinition(parameter, item);
                parameterList.add(parameter);
            });
            magicEntity.setParameters(parameterList);
        }
    }

    /**
     * 设置请求参数
     *
     * @param magicEntity
     * @param requestParamList
     */
    public void generateHeadersParam(ApiInfo magicEntity, List<InterfaceParameterConfig> requestParamList) {
        if (requestParamList != null && requestParamList.size() > 0) {
            List<Header> headerList = new ArrayList<>();
            for (InterfaceParameterConfig item : requestParamList) {
                Header header = new Header();
                setBaseDefinition(header, item);
                headerList.add(header);
            }
            magicEntity.setHeaders(headerList);
        }
    }

    /**
     * 生成path参数
     *
     * @param magicEntity
     * @param requestParamList
     */
    public void generatePathsParam(ApiInfo magicEntity, List<InterfaceParameterConfig> requestParamList) {
        if (requestParamList != null && requestParamList.size() > 0) {
            List<Path> pathList = new ArrayList<>();
            for (InterfaceParameterConfig item : requestParamList) {
                Path path = new Path();
                setBaseDefinition(path, item);
                pathList.add(path);
            }
            magicEntity.setPaths(pathList);
        }
    }

    /**
     * 生成path参数
     *
     * @param magicEntity
     * @param requestParamList
     */
    public void generateRequestBodyDefinition(ApiInfo magicEntity, List<InterfaceParameterConfig> requestParamList) {
        if (requestParamList != null && requestParamList.size() > 0) {
            InterfaceParameterConfig rootConfig = requestParamList.stream().filter(it->StringUtils.isBlank(it.getParameterId())).findFirst().orElse(null);
            AssertUtils.notNull(rootConfig,"requestBody根节点不能为空！");
            BaseDefinition root = new BaseDefinition();
            setBaseDefinition(root, rootConfig);
            // 构建树
            List<InterfaceParameterConfig> treeList = toTree(requestParamList,"0");
            List<BaseDefinition> baseDefinitionList = convertBaseDefinition(treeList);
            root.setChildren((ArrayList)baseDefinitionList);
            magicEntity.setRequestBodyDefinition(root);
        }
    }

    private List<BaseDefinition> convertBaseDefinition(List<InterfaceParameterConfig> list) {
        List<BaseDefinition> baseDefinitions = list.stream().map(it -> {
            BaseDefinition baseDefinition = new BaseDefinition();
            setBaseDefinition(baseDefinition, it);
            return baseDefinition;
        }).collect(Collectors.toList());
        if(list!=null && list.size()>0) {
            for (int i = 0; i < list.size(); i++) {
                BaseDefinition baseDefinition = baseDefinitions.get(i);
                InterfaceParameterConfig interfaceParameterConfig = list.get(i);
                baseDefinition.setChildren((ArrayList) convertBaseDefinition(interfaceParameterConfig.getChildren()));
            }
        }
        return baseDefinitions;
    }


    /**
     * 转换树
     *
     * @param list
     * @param parentId
     * @return
     */
    private List<InterfaceParameterConfig> toTree(List<InterfaceParameterConfig> list, String parentId) {
        List<InterfaceParameterConfig> parameterConfigList = list.stream().filter(it -> parentId.equals(it.getParameterParentId())).collect(Collectors.toList());
        parameterConfigList.forEach(it -> it.setChildren(toTree(list, it.getParameterId())));
        return parameterConfigList;
    }

    protected  Map<String, List<InterfaceParameterConfig>> getGroupInterfaceParameterConfigList(List<InterfaceParameterConfig> requestParamList){
        return requestParamList.stream().collect(Collectors.groupingBy(InterfaceParameterConfig::getParameterPosition, Collectors.toList()));
    }

    public void doGenerate(Map<String,Object> dataMap) throws TemplateException, IOException {
        ApiInfo magicEntity = new ApiInfo();
        InterfaceConfig interfaceConfig = (InterfaceConfig) dataMap.get("interfaceConfig");
        List<InterfaceParameterConfig> requestParamList = (List<InterfaceParameterConfig>) dataMap.get("interfaceParameterConfig");
        Map<String, List<InterfaceParameterConfig>> interfaceParameterMap = getGroupInterfaceParameterConfigList(requestParamList);
        // 1. 根据提交的配置生成接口信息配置
        generateInterfaceInfo(magicEntity,interfaceConfig);
        // 2. 根据提交的配置生成请求参数配置
        generateRequestParam(magicEntity,interfaceParameterMap.get("requestParam"));
        // 3. 根据提交的配置生成header。。。
        generateHeadersParam(magicEntity,interfaceParameterMap.get("headerParam"));
        // 4. 根据提交的配置生成path。。。
        generatePathsParam(magicEntity,interfaceParameterMap.get("pathParam"));
        // 5. 根据提交的配置生成requestBody。。。
        generateRequestBodyDefinition(magicEntity,interfaceParameterMap.get("requestBodyParam"));
        // 6. 根据提交的配置生成代码....
        generateScriptCode(magicEntity,dataMap);
        // 7. 进行保存
        resourceService.saveFolder(magicEntity);
    }
}
